﻿using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Text.RegularExpressions;
using Avalonia;
using Avalonia.Controls;
using CommunityToolkit.Mvvm.Input;

namespace OV2640Linker.ViewModels;

public partial class MainWindowViewModel : ViewModelBase
{
    private readonly List<List<string>> _pinLists = new();
    private const string _uncheckedColor = "#FFAEAEAE";
    private const string _checkedColor = "#FF72FF00";
    private const int _uncheckedWidth = 1;
    private const int _checkedWidth = 3;

    public MainWindowViewModel()
    {
        if (Design.IsDesignMode)
        {
            // 设计时初始化代码
            Title = "设计时标题";
            ColorWire1 = _checkedColor;
            WidthWire1 = _checkedWidth;
            CheckedPin1 = true;
            CheckedCam1 = true;
        }
        else
        {
            for (var i = 1; i < 41; i++)
            {
                _pinLists.Add([$"Pin{i}"]);
            }

            _pinLists.Add(["Cam1"]);
            _pinLists.Add(["Cam2"]);
            _pinLists.Add(["Cam3", "Pin12"]);
            _pinLists.Add(["Cam4", "Pin17"]);
            _pinLists.Add(["Cam5", "Pin18"]);
            _pinLists.Add(["Cam6", "Pin19"]);
            _pinLists.Add(["Cam7", "Pin20"]);
            _pinLists.Add(["Cam8", "Pin21"]);
            _pinLists.Add(["Cam9", "Pin11"]);
            _pinLists.Add(["Cam10", "Pin1", "GND"]);
            _pinLists.Add(["Cam11", "Pin10"]);
            _pinLists.Add(["Cam12", "Pin8"]);
            _pinLists.Add(["Cam13", "Pin9"]);
            _pinLists.Add(["Cam14", "2V8"]);
            _pinLists.Add(["Cam15", "1V5"]);
            _pinLists.Add(["Cam16", "Pin7"]);
            _pinLists.Add(["Cam17", "GND"]);
            _pinLists.Add(["Cam18", "Pin6"]);
            _pinLists.Add(["Cam19", "2V8"]);
            _pinLists.Add(["Cam20", "Pin5"]);
            _pinLists.Add(["Cam21", "2V8"]);
            _pinLists.Add(["Cam22", "Pin4"]);
            _pinLists.Add(["Cam23", "GND", "Pin1", "Pin40"]);
            _pinLists.Add(["Cam24"]);

            while (GroupList(_pinLists))
            {
            }

            CheckedText = null;
        }
    }

    #region 属性

    private string _title = "OV2640 Linker";

    public string Title
    {
        get => _title;
        set => SetProperty(ref _title, value);
    }

    private string _checkedText = "Cam1\r\nPin1";

    public string CheckedText
    {
        get => _checkedText;
        set => SetProperty(ref _checkedText, value);
    }

    private bool _checkedPin1;

    public bool CheckedPin1
    {
        get => _checkedPin1;
        set => SetProperty(ref _checkedPin1, value);
    }

    private bool _checkedPin2;

    public bool CheckedPin2
    {
        get => _checkedPin2;
        set => SetProperty(ref _checkedPin2, value);
    }

    private bool _checkedPin3;

    public bool CheckedPin3
    {
        get => _checkedPin3;
        set => SetProperty(ref _checkedPin3, value);
    }

    private bool _checkedPin4;

    public bool CheckedPin4
    {
        get => _checkedPin4;
        set => SetProperty(ref _checkedPin4, value);
    }

    private bool _checkedPin5;

    public bool CheckedPin5
    {
        get => _checkedPin5;
        set => SetProperty(ref _checkedPin5, value);
    }

    private bool _checkedPin6;

    public bool CheckedPin6
    {
        get => _checkedPin6;
        set => SetProperty(ref _checkedPin6, value);
    }

    private bool _checkedPin7;

    public bool CheckedPin7
    {
        get => _checkedPin7;
        set => SetProperty(ref _checkedPin7, value);
    }

    private bool _checkedPin8;

    public bool CheckedPin8
    {
        get => _checkedPin8;
        set => SetProperty(ref _checkedPin8, value);
    }

    private bool _checkedPin9;

    public bool CheckedPin9
    {
        get => _checkedPin9;
        set => SetProperty(ref _checkedPin9, value);
    }

    private bool _checkedPin10;

    public bool CheckedPin10
    {
        get => _checkedPin10;
        set => SetProperty(ref _checkedPin10, value);
    }

    private bool _checkedPin11;

    public bool CheckedPin11
    {
        get => _checkedPin11;
        set => SetProperty(ref _checkedPin11, value);
    }

    private bool _checkedPin12;

    public bool CheckedPin12
    {
        get => _checkedPin12;
        set => SetProperty(ref _checkedPin12, value);
    }

    private bool _checkedPin13;

    public bool CheckedPin13
    {
        get => _checkedPin13;
        set => SetProperty(ref _checkedPin13, value);
    }

    private bool _checkedPin14;

    public bool CheckedPin14
    {
        get => _checkedPin14;
        set => SetProperty(ref _checkedPin14, value);
    }

    private bool _checkedPin15;

    public bool CheckedPin15
    {
        get => _checkedPin15;
        set => SetProperty(ref _checkedPin15, value);
    }

    private bool _checkedPin16;

    public bool CheckedPin16
    {
        get => _checkedPin16;
        set => SetProperty(ref _checkedPin16, value);
    }

    private bool _checkedPin17;

    public bool CheckedPin17
    {
        get => _checkedPin17;
        set => SetProperty(ref _checkedPin17, value);
    }

    private bool _checkedPin18;

    public bool CheckedPin18
    {
        get => _checkedPin18;
        set => SetProperty(ref _checkedPin18, value);
    }

    private bool _checkedPin19;

    public bool CheckedPin19
    {
        get => _checkedPin19;
        set => SetProperty(ref _checkedPin19, value);
    }

    private bool _checkedPin20;

    public bool CheckedPin20
    {
        get => _checkedPin20;
        set => SetProperty(ref _checkedPin20, value);
    }

    private bool _checkedPin21;

    public bool CheckedPin21
    {
        get => _checkedPin21;
        set => SetProperty(ref _checkedPin21, value);
    }

    private bool _checkedPin22;

    public bool CheckedPin22
    {
        get => _checkedPin22;
        set => SetProperty(ref _checkedPin22, value);
    }

    private bool _checkedPin23;

    public bool CheckedPin23
    {
        get => _checkedPin23;
        set => SetProperty(ref _checkedPin23, value);
    }

    private bool _checkedPin24;

    public bool CheckedPin24
    {
        get => _checkedPin24;
        set => SetProperty(ref _checkedPin24, value);
    }

    private bool _checkedPin25;

    public bool CheckedPin25
    {
        get => _checkedPin25;
        set => SetProperty(ref _checkedPin25, value);
    }

    private bool _checkedPin26;

    public bool CheckedPin26
    {
        get => _checkedPin26;
        set => SetProperty(ref _checkedPin26, value);
    }

    private bool _checkedPin27;

    public bool CheckedPin27
    {
        get => _checkedPin27;
        set => SetProperty(ref _checkedPin27, value);
    }

    private bool _checkedPin28;

    public bool CheckedPin28
    {
        get => _checkedPin28;
        set => SetProperty(ref _checkedPin28, value);
    }

    private bool _checkedPin29;

    public bool CheckedPin29
    {
        get => _checkedPin29;
        set => SetProperty(ref _checkedPin29, value);
    }

    private bool _checkedPin30;

    public bool CheckedPin30
    {
        get => _checkedPin30;
        set => SetProperty(ref _checkedPin30, value);
    }

    private bool _checkedPin31;

    public bool CheckedPin31
    {
        get => _checkedPin31;
        set => SetProperty(ref _checkedPin31, value);
    }

    private bool _checkedPin32;

    public bool CheckedPin32
    {
        get => _checkedPin32;
        set => SetProperty(ref _checkedPin32, value);
    }

    private bool _checkedPin33;

    public bool CheckedPin33
    {
        get => _checkedPin33;
        set => SetProperty(ref _checkedPin33, value);
    }

    private bool _checkedPin34;

    public bool CheckedPin34
    {
        get => _checkedPin34;
        set => SetProperty(ref _checkedPin34, value);
    }

    private bool _checkedPin35;

    public bool CheckedPin35
    {
        get => _checkedPin35;
        set => SetProperty(ref _checkedPin35, value);
    }

    private bool _checkedPin36;

    public bool CheckedPin36
    {
        get => _checkedPin36;
        set => SetProperty(ref _checkedPin36, value);
    }

    private bool _checkedPin37;

    public bool CheckedPin37
    {
        get => _checkedPin37;
        set => SetProperty(ref _checkedPin37, value);
    }

    private bool _checkedPin38;

    public bool CheckedPin38
    {
        get => _checkedPin38;
        set => SetProperty(ref _checkedPin38, value);
    }

    private bool _checkedPin39;

    public bool CheckedPin39
    {
        get => _checkedPin39;
        set => SetProperty(ref _checkedPin39, value);
    }

    private bool _checkedPin40;

    public bool CheckedPin40
    {
        get => _checkedPin40;
        set => SetProperty(ref _checkedPin40, value);
    }

    private bool _checkedCam1;

    public bool CheckedCam1
    {
        get => _checkedCam1;
        set => SetProperty(ref _checkedCam1, value);
    }

    private bool _checkedCam2;

    public bool CheckedCam2
    {
        get => _checkedCam2;
        set => SetProperty(ref _checkedCam2, value);
    }

    private bool _checkedCam3;

    public bool CheckedCam3
    {
        get => _checkedCam3;
        set => SetProperty(ref _checkedCam3, value);
    }

    private bool _checkedCam4;

    public bool CheckedCam4
    {
        get => _checkedCam4;
        set => SetProperty(ref _checkedCam4, value);
    }

    private bool _checkedCam5;

    public bool CheckedCam5
    {
        get => _checkedCam5;
        set => SetProperty(ref _checkedCam5, value);
    }

    private bool _checkedCam6;

    public bool CheckedCam6
    {
        get => _checkedCam6;
        set => SetProperty(ref _checkedCam6, value);
    }

    private bool _checkedCam7;

    public bool CheckedCam7
    {
        get => _checkedCam7;
        set => SetProperty(ref _checkedCam7, value);
    }

    private bool _checkedCam8;

    public bool CheckedCam8
    {
        get => _checkedCam8;
        set => SetProperty(ref _checkedCam8, value);
    }

    private bool _checkedCam9;

    public bool CheckedCam9
    {
        get => _checkedCam9;
        set => SetProperty(ref _checkedCam9, value);
    }

    private bool _checkedCam10;

    public bool CheckedCam10
    {
        get => _checkedCam10;
        set => SetProperty(ref _checkedCam10, value);
    }

    private bool _checkedCam11;

    public bool CheckedCam11
    {
        get => _checkedCam11;
        set => SetProperty(ref _checkedCam11, value);
    }

    private bool _checkedCam12;

    public bool CheckedCam12
    {
        get => _checkedCam12;
        set => SetProperty(ref _checkedCam12, value);
    }

    private bool _checkedCam13;

    public bool CheckedCam13
    {
        get => _checkedCam13;
        set => SetProperty(ref _checkedCam13, value);
    }

    private bool _checkedCam14;

    public bool CheckedCam14
    {
        get => _checkedCam14;
        set => SetProperty(ref _checkedCam14, value);
    }

    private bool _checkedCam15;

    public bool CheckedCam15
    {
        get => _checkedCam15;
        set => SetProperty(ref _checkedCam15, value);
    }

    private bool _checkedCam16;

    public bool CheckedCam16
    {
        get => _checkedCam16;
        set => SetProperty(ref _checkedCam16, value);
    }

    private bool _checkedCam17;

    public bool CheckedCam17
    {
        get => _checkedCam17;
        set => SetProperty(ref _checkedCam17, value);
    }

    private bool _checkedCam18;

    public bool CheckedCam18
    {
        get => _checkedCam18;
        set => SetProperty(ref _checkedCam18, value);
    }

    private bool _checkedCam19;

    public bool CheckedCam19
    {
        get => _checkedCam19;
        set => SetProperty(ref _checkedCam19, value);
    }

    private bool _checkedCam20;

    public bool CheckedCam20
    {
        get => _checkedCam20;
        set => SetProperty(ref _checkedCam20, value);
    }

    private bool _checkedCam21;

    public bool CheckedCam21
    {
        get => _checkedCam21;
        set => SetProperty(ref _checkedCam21, value);
    }

    private bool _checkedCam22;

    public bool CheckedCam22
    {
        get => _checkedCam22;
        set => SetProperty(ref _checkedCam22, value);
    }

    private bool _checkedCam23;

    public bool CheckedCam23
    {
        get => _checkedCam23;
        set => SetProperty(ref _checkedCam23, value);
    }

    private bool _checkedCam24;

    public bool CheckedCam24
    {
        get => _checkedCam24;
        set => SetProperty(ref _checkedCam24, value);
    }

    private string _colorWire1 = "#FFAEAEAE";

    public string ColorWire1
    {
        get => _colorWire1;
        set => SetProperty(ref _colorWire1, value);
    }

    private string _colorWire2 = "#FFAEAEAE";

    public string ColorWire2
    {
        get => _colorWire2;
        set => SetProperty(ref _colorWire2, value);
    }

    private string _colorWire3 = "#FFAEAEAE";

    public string ColorWire3
    {
        get => _colorWire3;
        set => SetProperty(ref _colorWire3, value);
    }

    private string _colorWire4 = "#FFAEAEAE";

    public string ColorWire4
    {
        get => _colorWire4;
        set => SetProperty(ref _colorWire4, value);
    }

    private string _colorWire5 = "#FFAEAEAE";

    public string ColorWire5
    {
        get => _colorWire5;
        set => SetProperty(ref _colorWire5, value);
    }

    private string _colorWire6 = "#FFAEAEAE";

    public string ColorWire6
    {
        get => _colorWire6;
        set => SetProperty(ref _colorWire6, value);
    }

    private string _colorWire7 = "#FFAEAEAE";

    public string ColorWire7
    {
        get => _colorWire7;
        set => SetProperty(ref _colorWire7, value);
    }

    private string _colorWire8 = "#FFAEAEAE";

    public string ColorWire8
    {
        get => _colorWire8;
        set => SetProperty(ref _colorWire8, value);
    }

    private string _colorWire9 = "#FFAEAEAE";

    public string ColorWire9
    {
        get => _colorWire9;
        set => SetProperty(ref _colorWire9, value);
    }

    private string _colorWire10 = "#FFAEAEAE";

    public string ColorWire10
    {
        get => _colorWire10;
        set => SetProperty(ref _colorWire10, value);
    }

    private string _colorWire11 = "#FFAEAEAE";

    public string ColorWire11
    {
        get => _colorWire11;
        set => SetProperty(ref _colorWire11, value);
    }

    private string _colorWire12 = "#FFAEAEAE";

    public string ColorWire12
    {
        get => _colorWire12;
        set => SetProperty(ref _colorWire12, value);
    }

    private string _colorWire13 = "#FFAEAEAE";

    public string ColorWire13
    {
        get => _colorWire13;
        set => SetProperty(ref _colorWire13, value);
    }

    private string _colorWire14 = "#FFAEAEAE";

    public string ColorWire14
    {
        get => _colorWire14;
        set => SetProperty(ref _colorWire14, value);
    }

    private string _colorWire15 = "#FFAEAEAE";

    public string ColorWire15
    {
        get => _colorWire15;
        set => SetProperty(ref _colorWire15, value);
    }

    private string _colorWire16 = "#FFAEAEAE";

    public string ColorWire16
    {
        get => _colorWire16;
        set => SetProperty(ref _colorWire16, value);
    }

    private string _colorWire17 = "#FFAEAEAE";

    public string ColorWire17
    {
        get => _colorWire17;
        set => SetProperty(ref _colorWire17, value);
    }

    private string _colorWire18 = "#FFAEAEAE";

    public string ColorWire18
    {
        get => _colorWire18;
        set => SetProperty(ref _colorWire18, value);
    }

    private string _colorWire19 = "#FFAEAEAE";

    public string ColorWire19
    {
        get => _colorWire19;
        set => SetProperty(ref _colorWire19, value);
    }

    private string _colorWire20 = "#FFAEAEAE";

    public string ColorWire20
    {
        get => _colorWire20;
        set => SetProperty(ref _colorWire20, value);
    }

    private string _colorWire21 = "#FFAEAEAE";

    public string ColorWire21
    {
        get => _colorWire21;
        set => SetProperty(ref _colorWire21, value);
    }

    private string _colorWire22 = "#FFAEAEAE";

    public string ColorWire22
    {
        get => _colorWire22;
        set => SetProperty(ref _colorWire22, value);
    }

    private string _colorWire23 = "#FFAEAEAE";

    public string ColorWire23
    {
        get => _colorWire23;
        set => SetProperty(ref _colorWire23, value);
    }

    private string _colorWire24 = "#FFAEAEAE";

    public string ColorWire24
    {
        get => _colorWire24;
        set => SetProperty(ref _colorWire24, value);
    }

    private int _widthWire1 = 1;

    public int WidthWire1
    {
        get => _widthWire1;
        set => SetProperty(ref _widthWire1, value);
    }

    private int _widthWire2 = 1;

    public int WidthWire2
    {
        get => _widthWire2;
        set => SetProperty(ref _widthWire2, value);
    }

    private int _widthWire3 = 1;

    public int WidthWire3
    {
        get => _widthWire3;
        set => SetProperty(ref _widthWire3, value);
    }

    private int _widthWire4 = 1;

    public int WidthWire4
    {
        get => _widthWire4;
        set => SetProperty(ref _widthWire4, value);
    }

    private int _widthWire5 = 1;

    public int WidthWire5
    {
        get => _widthWire5;
        set => SetProperty(ref _widthWire5, value);
    }

    private int _widthWire6 = 1;

    public int WidthWire6
    {
        get => _widthWire6;
        set => SetProperty(ref _widthWire6, value);
    }

    private int _widthWire7 = 1;

    public int WidthWire7
    {
        get => _widthWire7;
        set => SetProperty(ref _widthWire7, value);
    }

    private int _widthWire8 = 1;

    public int WidthWire8
    {
        get => _widthWire8;
        set => SetProperty(ref _widthWire8, value);
    }

    private int _widthWire9 = 1;

    public int WidthWire9
    {
        get => _widthWire9;
        set => SetProperty(ref _widthWire9, value);
    }

    private int _widthWire10 = 1;

    public int WidthWire10
    {
        get => _widthWire10;
        set => SetProperty(ref _widthWire10, value);
    }

    private int _widthWire11 = 1;

    public int WidthWire11
    {
        get => _widthWire11;
        set => SetProperty(ref _widthWire11, value);
    }

    private int _widthWire12 = 1;

    public int WidthWire12
    {
        get => _widthWire12;
        set => SetProperty(ref _widthWire12, value);
    }

    private int _widthWire13 = 1;

    public int WidthWire13
    {
        get => _widthWire13;
        set => SetProperty(ref _widthWire13, value);
    }

    private int _widthWire14 = 1;

    public int WidthWire14
    {
        get => _widthWire14;
        set => SetProperty(ref _widthWire14, value);
    }

    private int _widthWire15 = 1;

    public int WidthWire15
    {
        get => _widthWire15;
        set => SetProperty(ref _widthWire15, value);
    }

    private int _widthWire16 = 1;

    public int WidthWire16
    {
        get => _widthWire16;
        set => SetProperty(ref _widthWire16, value);
    }

    private int _widthWire17 = 1;

    public int WidthWire17
    {
        get => _widthWire17;
        set => SetProperty(ref _widthWire17, value);
    }

    private int _widthWire18 = 1;

    public int WidthWire18
    {
        get => _widthWire18;
        set => SetProperty(ref _widthWire18, value);
    }

    private int _widthWire19 = 1;

    public int WidthWire19
    {
        get => _widthWire19;
        set => SetProperty(ref _widthWire19, value);
    }

    private int _widthWire20 = 1;

    public int WidthWire20
    {
        get => _widthWire20;
        set => SetProperty(ref _widthWire20, value);
    }

    private int _widthWire21 = 1;

    public int WidthWire21
    {
        get => _widthWire21;
        set => SetProperty(ref _widthWire21, value);
    }

    private int _widthWire22 = 1;

    public int WidthWire22
    {
        get => _widthWire22;
        set => SetProperty(ref _widthWire22, value);
    }

    private int _widthWire23 = 1;

    public int WidthWire23
    {
        get => _widthWire23;
        set => SetProperty(ref _widthWire23, value);
    }

    private int _widthWire24 = 1;

    public int WidthWire24
    {
        get => _widthWire24;
        set => SetProperty(ref _widthWire24, value);
    }
    
    #endregion

    #region 命令

    private RelayCommand<string> _clickedPinCmd;

    public RelayCommand<string> ClickedPinCmd =>
        _clickedPinCmd ??= new RelayCommand<string>(ExecuteClickedPinCmd);

    private void ExecuteClickedPinCmd(string pin)
    {
        CheckedText = null;
        foreach (var pinList in _pinLists)
        {
            if (pinList.Contains(pin))
            {
                var stringBuilder = new StringBuilder();
                foreach (var pinItem in pinList)
                {
                    Changed(pinItem, true);
                    stringBuilder.AppendFormat($"{pinItem}\r\n");
                }

                CheckedText = stringBuilder.ToString();
            }
            else
            {
                foreach (var pinItem in pinList)
                {
                    Changed(pinItem, false);
                }
            }
        }
    }

    #endregion

    #region 方法

    private bool GroupList(List<List<string>> originList)
    {
        var hasGrouped = false;
        var clonedList = originList.Select(innerList => innerList.ToList()).ToList();
        originList.Clear();
        foreach (var itemList in clonedList)
        {
            var has = false;
            foreach (var pinList in originList)
            {
                //检测是否存在交集
                if (!pinList.Intersect(itemList).Any()) continue;
                hasGrouped = true;
                foreach (var itemPin in itemList)
                {
                    if (pinList.Contains(itemPin))
                        continue;
                    pinList.Add(itemPin);
                }

                has = true;
                break;
            }

            if (has)
                continue;
            originList.Add(itemList);
        }

        return hasGrouped;
    }

    private void Changed(string pinName, bool state)
    {
        this.GetType().GetProperty($"Checked{pinName}")?.SetValue(this, state);
        if (!pinName.StartsWith(("Cam"))) return;
        var color=_uncheckedColor;
        var width = _uncheckedWidth;
        if (state)
        {
            color = _checkedColor;
            width = _checkedWidth;
        }

        var match = Regex.Match(pinName, "\\d+");
        if (!match.Success) return;
        this.GetType().GetProperty($"ColorWire{match.Value}")?.SetValue(this, color);
        this.GetType().GetProperty($"WidthWire{match.Value}")?.SetValue(this, width);
    }

    #endregion
}